#include"TextClass.h"
#include<iostream>
#include<vector>

using namespace std;

class DirectQuery:virtual public TextClass{
    public:
	DirectQuery(){
//	    cout<<"build DirectQuery none"<<endl;
	}
	DirectQuery(string SearchWord,string SearchFrom):
	    TextClass(SearchFrom),
	    SearchWord(SearchWord){
//	    cout<<"build DirectQuery with"<<endl;
	}
	~DirectQuery(){
//	    cout<<"delete DirectQuery"<<endl;
	}

	void SetSearchWord(string word){
//	    cout<<"DirectQuery SetSearchWord"<<endl;
	    SearchWord=word;
	}
	vector<int>getDirectLine(){
	    return DirectLine;
	}
	virtual void Result(){
//	    cout<<"DirectLine Result"<<endl;
	    DirectLine.erase(DirectLine.begin(),DirectLine.end());
	    DirectLine=SearchResult(getBTree().getRoot());
	}

    private:
    public:
	vector<int> SearchResult(Tree *t){
	    
	    vector<int>p;
	    if(t==nullptr){
		return p;
	    }
	    else if(t->KeyWord > SearchWord){
		p=SearchResult(t->left);
	    }
	    else if(t->KeyWord < SearchWord){
		p=SearchResult(t->right);
	    }
	    else{
		p=t->LineNum;
	    }
	    return p;
	}

    private:
	string SearchWord;
	vector<int>DirectLine;
};


class AndQuery:virtual public TextClass{
    public:
	AndQuery(){
//	    cout<<"build AndQuery none"<<endl;
	}
	AndQuery(string FirstWord,string SecondWord,string SearchFrom):
	    TextClass(SearchFrom),
	    FirstWord(FirstWord),
	    SecondWord(SecondWord){
//	    cout<<"build AndQuery with"<<endl;
	}
	~AndQuery(){
//	    cout<<"delete AndQuery"<<endl;
	}

	vector<int>getAndLine(){
	    return AndLine;
	}

	void SetFirstWord(string word){
//	    cout<<"AndQuery SetFirstWord"<<endl;
	    FirstWord=word;
	}
	void SetSecondWord(string word){
//	    cout<<"AndQuery SetSecondWord"<<endl;
	    SecondWord=word;
	}

	virtual void Result(){
//	    cout<<"AndQuery Result"<<endl;
	    AndLine.erase(AndLine.begin(),AndLine.end());
	    auto First=SearchResult(FirstWord,getBTree().getRoot());
	    auto Second=SearchResult(SecondWord,getBTree().getRoot());
	    
	    for(auto it=Second.begin();it!=Second.end();it++){
		for(auto in=First.begin();in!=First.end();in++){
		    if(*in==*it){
			AndLine.push_back(*it);
			break;
		    }
		}
	    }
	}

    private:
    public:
	vector<int> SearchResult(string SearchWord,Tree *t){
	    
	    vector<int>p;
	    if(t==nullptr){
		return p;
	    }
	    else if(t->KeyWord > SearchWord){
		p=SearchResult(SearchWord,t->left);
	    }
	    else if(t->KeyWord < SearchWord){
		p=SearchResult(SearchWord,t->right);
	    }
	    else{
		p=t->LineNum;
	    }
	    return p;
	}

    private:
	string FirstWord;
	string SecondWord;
	vector<int>AndLine;
};


class NotQuery:virtual public DirectQuery{
    public:
	NotQuery(){   
//	    cout<<"build NotQuery none"<<endl;
	}
	NotQuery(string SearchWord,string SearchFrom):
	    DirectQuery(SearchWord,SearchFrom){
//		cout<<"build NotQuery with"<<endl;
	}
	~NotQuery(){
//	    cout<<"delete NotQuery"<<endl;
	}

	vector<int>getNotLine(){
	    return NotLine;
	}

	void Result(vector<int>v){

//	    cout<<"NotQuery Result with"<<endl;
	    NotLine.erase(NotLine.begin(),NotLine.end());
	    map<int,string> s=getBTree().getLineText();
	    for(auto it=v.begin();it!=v.end();it++){
		s.erase(*it);
	    }
	    for(auto it=s.begin();it!=s.end();it++){
		NotLine.push_back(it->first);
	    }
	}

	void Result(){
//	    cout<<"NotQuery Result none"<<endl;
	    NotLine.erase(NotLine.begin(),NotLine.end());
	    vector<int>tmp;
	    tmp=SearchResult(getBTree().getRoot()); 
	    map<int,string> s=getBTree().getLineText();
	    for(auto it=tmp.begin();it!=tmp.end();it++){
		s.erase(*it);
	    }
	    for(auto it=s.begin();it!=s.end();it++){
		NotLine.push_back(it->first);

	    }
	}

    private:
	vector<int>NotLine;
};

class OrQuery:virtual public TextClass{
    public:
	OrQuery(){
//	    cout<<"build OrQuery none"<<endl;
	}
	OrQuery(string FirstWord,string SecondWord,string SearchFrom):
	    TextClass(SearchFrom),
	    FirstWord(FirstWord),
	    SecondWord(SecondWord){
//	    cout<<"build OrQuery with"<<endl;
	}
	~OrQuery(){
//	    cout<<"delete OrQuery"<<endl;
	}

	vector<int>getOrLine(){
	    return OrLine;
	}

	void SetFirstWord(string word){
//	    cout<<"OrQuery SetFirstWord"<<endl;
	    FirstWord=word;
	}
	void SetSecondWord(string word){
//	    cout<<"OrQuery SetSecondWord"<<endl;
	    SecondWord=word;
	}

	virtual void Result(){
//	    cout<<"OrQuery Result"<<endl;
	    OrLine.erase(OrLine.begin(),OrLine.end());
	    OrLine=SearchResult(FirstWord,getBTree().getRoot());
	    auto Second=SearchResult(SecondWord,getBTree().getRoot());
	    
	    for(auto it=Second.begin();it!=Second.end();it++){
		auto in=OrLine.begin();
		for(;in!=OrLine.end();in++){
		    if(*in==*it)break;
		}
		if(in==OrLine.end())OrLine.push_back(*it);
	    }
	}

    private:
    public:
	vector<int> SearchResult(string SearchWord,Tree *t){
	    
	    vector<int>p;
	    if(t==nullptr){
		return p;
	    }
	    else if(t->KeyWord > SearchWord){
		p=SearchResult(SearchWord,t->left);
	    }
	    else if(t->KeyWord < SearchWord){
		p=SearchResult(SearchWord,t->right);
	    }
	    else{
		p=t->LineNum;
	    }
	    return p;
	}

    private:
	string FirstWord;
	string SecondWord;
	vector<int>OrLine;
};

